package subumbo.audio.core
{
	import __AS3__.vec.Vector;
	
	import flash.utils.Dictionary;
	
	import subumbo.audio.driver.AudioDriver;
	
	public class Mixer
	{
		protected var _input:Vector.<IAudioProcessor>;
		protected var _channels:Vector.<Vector.<Vector.<Number>>>;
		protected var _volumes:Vector.<Vector.<Number>>;
		protected var _processMap:Vector.<int>;
		
		private var _buffer:Vector.<Vector.<Number>>;
		private var _inputLength:int;
		
		static public const NUM_CHANNELS:int = 1;
		
		public function Mixer(input:Vector.<IAudioProcessor> = null)
		{
			_channels = new Vector.<Vector.<Vector.<Number>>>();
			_channels[0] = new Vector.<Vector.<Number>>();
			_channels[1] = new Vector.<Vector.<Number>>();
			_channels[0][0] = new Vector.<Number>( AudioDriver.SIZE, true ); 
			_channels[0][1] = new Vector.<Number>( AudioDriver.SIZE, true );
			_channels[1][0] = new Vector.<Number>( AudioDriver.SIZE, true ); 
			_channels[1][1] = new Vector.<Number>( AudioDriver.SIZE, true );
			
			_volumes = new Vector.<Vector.<Number>>();
			_volumes[0] = new Vector.<Number>( 2, true ); 
			_volumes[1] = new Vector.<Number>( 2, true );
			
			
			_buffer = new Vector.<Vector.<Number>>( 2, true)
			_buffer[0] = new Vector.<Number>( AudioDriver.SIZE, true );
			_buffer[1] = new Vector.<Number>( AudioDriver.SIZE, true );
			
			for(var i:int = 0; i < AudioDriver.SIZE; i++)
			{
				_channels[0][0][i] = 0.0;
				_channels[0][1][i] = 0.0;
				_channels[1][0][i] = 0.0;
				_channels[1][1][i] = 0.0;	
			}
			_volumes[0][0] = 1.0;
			_volumes[0][1] = 1.0;
			_volumes[1][0] = 1.0;
			_volumes[1][1] = 1.0;
			
			
			this.input = input;
		}
		
		public function volume(channelID:int, value:Number):void
		{
			_input[channelID].volume = value;
		}
		
		public function crossFade(channelID1:int, channelID2:int, value:Number):void
		{
			_volumes[channelID1][0] = 1 * value;
			_volumes[channelID1][1] = 1 * value;
			
			_volumes[channelID2][0] = 1 * (1-value);
			_volumes[channelID2][1] = 1 * (1-value);
		}
		
		public function process( buffer: Vector.<Vector.<Number>> ):void
		{
			var i: int = 0;
			var n: int = _inputLength;
			for( ; i < n ; ++i )
			{
				_input[i].process(_channels[_processMap[i]]);
				//_input[i].process(buffer);
			}
		
			var le: Vector.<Number> = buffer[0];
			var ri: Vector.<Number> = buffer[1];
			var j:int = 0;
			var k:int;
			var l:int = _channels.length;
			var t:int 
			var size:int = AudioDriver.SIZE;	
	      for (; j < size; ++j) 
		    {	
		    	le[j] = _channels[0][0][j] * _volumes[0][0];
			     ri[j] = _channels[0][1][j] * _volumes[0][1];
		    	k=1;
		    	for(; k < l; ++k)
		    	{	
		     		le[j] += _channels[k][0][j] * _volumes[k][0];
			      	ri[j] += _channels[k][1][j] * _volumes[k][1];	
		    	}
	  		}  
		}
		
		public function set input(val:Vector.<IAudioProcessor>):void
		{
			_input = val;
		}
		
		public function get input():Vector.<IAudioProcessor>
		{
			return _input;
		}
		
		
		public function cleanUp(channelEffects:Dictionary, generators:Dictionary):void
		{
			var i:int = 0;
			var index:int;
			_processMap = new Vector.<int>(_input.length, true);
			for each (var value:Object in generators)
			{
					index = _input.indexOf(value);
					if(index == -1) continue;
						_channels[i] = new Vector.<Vector.<Number>>();
						_volumes[i] = new Vector.<Number>( 2, true );
						_volumes[i][0] = 1.0;
						_volumes[i][1] = 1.0;
						_channels[i][0] = new Vector.<Number>( AudioDriver.SIZE, true ); 
						_channels[i][1] = new Vector.<Number>( AudioDriver.SIZE, true );
						if(value.processIndex)_processMap[i] = value.processIndex;
					i++
			}
			_inputLength = _input.length;		
		}
	}
}